//
//  FlickrPhotosViewController.swift
//  FlickrSearch
//
//  Created by cygarm on 15/7/28.
//  Copyright (c) 2015年 cygarm. All rights reserved.
//

import UIKit


class FlickrPhotosViewController: UICollectionViewController {

	private let reuseIdentifier = "FlickrCell"
	private let sectionInsets = UIEdgeInsets(top: 50.0, left: 20.0, bottom: 50.0, right: 20.0)
	
	private var searches = [FlickrSearchResults]()
	private let flickr = Flickr()
	
	private var selectedPhotos = [FlickrPhoto]()
	private let shareTextLabel = UILabel()
	
	
	/*
	
	1.largePhotoIndexPath is an optional that will hold the index path of the tapped photo, if there is one.
	2.Whenever this property gets updated, the collection view needs to be updated. a didSet property observer is the safest place to manage this. There may be two cells that need reloading, if the user has tapped one cell then another, or just one if the user has tapped the first cell, then tapped it again to shrink.
	3.performBatchUpdates will animate any changes to the collection view performed inside the block. You want it to reload the affected cells. The return statement is there because a single-statement closure is treated differently by Swift and it tries to infer a return value from it!
	4.Once the animated update has finished, it’s a nice touch to scroll the enlarged cell to the middle of the screen

	*/
	// 1
	var largePhotoIndexPath : NSIndexPath? {
		didSet {
			// 2
			var indexPaths = [NSIndexPath]()
			if largePhotoIndexPath != nil {
				indexPaths.append(largePhotoIndexPath!)
			}
			if oldValue != nil {
				indexPaths.append(oldValue!)
			}
			// 3
			self.collectionView?.performBatchUpdates({
				self.collectionView?.reloadItemsAtIndexPaths(indexPaths)
				return
				}){
					completed in
					// 4
					if self.largePhotoIndexPath != nil {
						self.collectionView?.scrollToItemAtIndexPath(
							self.largePhotoIndexPath!, 
							atScrollPosition: .CenteredVertically, 
							animated: true)
					}
			}
		}
	}
	
	var sharing : Bool = false {
		didSet {
			collectionView?.allowsMultipleSelection = sharing
			collectionView?.selectItemAtIndexPath(nil, animated: true, scrollPosition: .None)
			selectedPhotos.removeAll(keepCapacity: false)
			if sharing && largePhotoIndexPath != nil {
				largePhotoIndexPath = nil
			}
			
			let shareButton = self.navigationItem.rightBarButtonItem! as UIBarButtonItem
			if sharing {
				updateSharedPhotoCount()
				let sharingDetailItem = UIBarButtonItem(customView: shareTextLabel)
				self.navigationItem.setRightBarButtonItems([shareButton, sharingDetailItem], animated: true)
			}
			else {
				self.navigationItem.setRightBarButtonItems([shareButton], animated: true)
			}
		}
	}
	
	func photoForIndexPath(indexPath: NSIndexPath) -> FlickrPhoto {
		return searches[indexPath.section].searchResults[indexPath.row]
	}
	
	func updateSharedPhotoCount() {
		shareTextLabel.textColor = themeColor
		shareTextLabel.text = "\(selectedPhotos.count) photos selected"
		shareTextLabel.sizeToFit()
	}

	@IBAction func share(sender: AnyObject) {
		if searches.isEmpty {
			return
		}
		
		if !selectedPhotos.isEmpty {
			var imageArray = [UIImage]()
			for photo in self.selectedPhotos {
				imageArray.append(photo.thumbnail!)
			}
			
			let shareScreen = UIActivityViewController(activityItems: imageArray, applicationActivities: nil)
			let popover = UIPopoverController(contentViewController: shareScreen)
			popover.presentPopoverFromBarButtonItem(self.navigationItem.rightBarButtonItem! as UIBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
		}
		
		sharing = !sharing
	}
}

extension FlickrPhotosViewController: UICollectionViewDelegate {
	override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
		NSLog("[\(__FUNCTION__):\(__LINE__)]largePhotoIndexPath=\(largePhotoIndexPath)")
		if sharing {
			return true
		}
		
		if largePhotoIndexPath == indexPath {
			largePhotoIndexPath = nil
		}
		else {
			largePhotoIndexPath = indexPath
		}
		return false
	}
	
	override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
		if sharing {
			let photo = photoForIndexPath(indexPath)
			selectedPhotos.append(photo)
			updateSharedPhotoCount()
		}
	}
	
	override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
		if sharing {
			if let foundIndex = find(selectedPhotos, photoForIndexPath(indexPath)) {
				selectedPhotos.removeAtIndex(foundIndex)
				updateSharedPhotoCount()
			}
		}
	}
}

extension FlickrPhotosViewController: UICollectionViewDelegateFlowLayout {
	func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
		let flickrPhoto = photoForIndexPath(indexPath)

		// 大图
		if indexPath == largePhotoIndexPath {
			var size = collectionView.bounds.size
			size.height -= topLayoutGuide.length
			size.height -= (sectionInsets.top + sectionInsets.right)
			size.width -= (sectionInsets.left + sectionInsets.right)
			return flickrPhoto.sizeToFillWidthOfSize(size)
		}
		// 缩略图
		if var size = flickrPhoto.thumbnail?.size {
			size.width += 10
			size.height += 10
			return size
		}
		return CGSize(width: 100, height: 100)
	}
	
	func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
		return sectionInsets
	}
}

/*

1.There’s one search per section, so the number of sections is the count of the searches array.
2.The number of items in a section is the count of the searchResults array from the relevant FlickrSearch object.
3.This is a placeholder method just to return a blank cell – you’ll be populating it later. Note that collection views require you to have registered a cell with a reuse identifier, or a runtime error will occur.

*/
extension FlickrPhotosViewController: UICollectionViewDataSource {
    //1
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
			NSLog("[\(__FUNCTION__):\(__LINE__)]searches.count=\(searches.count)")

        return searches.count
    }
    
    //2
    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return searches[section].searchResults.count
    }
    
    //3
	override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
		let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! FlickrPhotoCell
		let flickrPhoto = photoForIndexPath(indexPath)
		
		
		/*
		
		1.Always stop the activity spinner – you could be reusing a cell that was previously loading an image
		2.This part is as before – if you’re not looking at the large photo, just set the thumbnail and return
		3.If the large image is already loaded, set it and return
		4.By this point, you want the large image, but it doesn’t exist yet. Set the thumbnail image and start the spinner going. The thumbnail will stretch until the download is complete
		5.Ask for the large image from Flickr. This loads the image asynchronously and has a completion block
		6.The load has finished, so stop the spinner
		7.If there was an error or no photo was loaded, there’s not much you can do.
		8.Check that the large photo index path hasn’t changed while the download was happening, and retrieve whatever cell is currently in use for that index path (it may not be the original cell, since scrolling could have happened) and set the large image.

		*/
		//1
		cell.activityIndicator.stopAnimating()
		
		//2
		if indexPath != largePhotoIndexPath {
			cell.imageView.image = flickrPhoto.thumbnail
			return cell
		}
		
		//3
		if flickrPhoto.largeImage != nil {
			cell.imageView.image = flickrPhoto.largeImage
			return cell
		}
		
		//4
		cell.imageView.image = flickrPhoto.thumbnail
		cell.activityIndicator.startAnimating()
		
		//5
		flickrPhoto.loadLargeImage {
			loadedFlickrPhoto, error in
			
			//6
			cell.activityIndicator.stopAnimating()
			
			//7
			if error != nil {
				return
			}
			
			if loadedFlickrPhoto.largeImage == nil {
				return
			}
			
			// 8
			if indexPath == self.largePhotoIndexPath {
				if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? FlickrPhotoCell {
					cell.imageView.image = loadedFlickrPhoto.largeImage
				}
			}
		}
		
		return cell
	}
	
  override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    /*

    1.The kind parameter is supplied by the layout object and indicates which sort of supplementary view is being asked for.
    2.UICollectionElementKindSectionHeader is a supplementary view kind belonging to the flow layout. By checking that box in the storyboard to add a section header, you told the flow layout that it needs to start asking for these views. There is also a UICollectionElementKindSectionFooter, which you’re not currently using. If you don’t use the flow layout, you don’t get header and footer views for free like this.
    3.The header view is dequeued using the identifier added in the storyboard. This works just like cell dequeuing. The label’s text is then set to the relevant search term.
    4.An assert is placed here to make it clear to other developers (including future you!) that you’re not expecting to be asked for anything other than a header view.

    */
    // 1
    switch kind {
      // 2
    case UICollectionElementKindSectionHeader:
      // 3
      let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "FlickrPhotoHeaderView", forIndexPath: indexPath) as! FlickrPhotoHeaderView
      headerView.label.text = searches[indexPath.section].searchTerm
      return headerView
    default:
      // 4
      assert(false, "Unexpected element kind")
    }
  }
}

/*

1.After adding an activity view, use the Flickr wrapper class I provided to search Flickr for photos that match the given search term asynchronously. When the search completes, the completion block will be called with a the result set of FlickrPhoto objects, and an error (if there was one).
2.Log any errors to the console. Obviously, in a production application you would want to display these errors to the user.
3.The results get logged and added to the front of the searches array
4.At this stage, you have new data and need to refresh the UI. You’re using the insertSections method to add your results at the top of the list.

*/

extension FlickrPhotosViewController: UITextFieldDelegate {
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        // 1
        let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
        textField.addSubview(activityIndicator)
        activityIndicator.frame = textField.bounds
        activityIndicator.startAnimating()
        flickr.searchFlickrForTerm(textField.text) {
            results, error in
            
            //2
            activityIndicator.removeFromSuperview()
            if error != nil {
                println("Error searching : \(error)")
            }
            
            if results != nil {
                //3
                println("Found \(results!.searchResults.count) matching \(results!.searchTerm)")
                self.searches.insert(results!, atIndex: 0)
                
                //4
                self.collectionView?.reloadData()
            }
        }
        
        textField.text = nil
        textField.resignFirstResponder()
        return true
    }
}
